package com.tianhai.db;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * LockManager完整单元测试
 */
public class LockManagerTest {
    
    public static void main(String[] args) {
        System.out.println("========================================");
        System.out.println("      LockManager 两阶段锁测试");
        System.out.println("========================================\n");
        
        int totalTests = 0;
        int passedTests = 0;
        
        // 测试1: 单事务获取共享锁
        System.out.println("【测试1】单事务获取共享锁");
        try {
            LockManager lockManager = new LockManager();
            boolean result = lockManager.acquireLock(1, "table1", LockManager.LockType.SHARED);
            
            if (result && lockManager.holdsLock(1, "table1")) {
                System.out.println("✓ 成功获取共享锁");
                passedTests++;
            } else {
                System.out.println("✗ 获取共享锁失败");
            }
        } catch (Exception e) {
            System.out.println("✗ 异常: " + e.getMessage());
        }
        totalTests++;
        System.out.println();
        
        // 测试2: 单事务获取排他锁
        System.out.println("【测试2】单事务获取排他锁");
        try {
            LockManager lockManager = new LockManager();
            boolean result = lockManager.acquireLock(1, "table1", LockManager.LockType.EXCLUSIVE);
            
            if (result && lockManager.holdsLock(1, "table1")) {
                System.out.println("✓ 成功获取排他锁");
                passedTests++;
            } else {
                System.out.println("✗ 获取排他锁失败");
            }
        } catch (Exception e) {
            System.out.println("✗ 异常: " + e.getMessage());
        }
        totalTests++;
        System.out.println();
        
        // 测试3: 多事务获取共享锁（兼容）
        System.out.println("【测试3】多事务获取共享锁（兼容）");
        try {
            LockManager lockManager = new LockManager();
            boolean result1 = lockManager.acquireLock(1, "table1", LockManager.LockType.SHARED);
            boolean result2 = lockManager.acquireLock(2, "table1", LockManager.LockType.SHARED);
            
            if (result1 && result2 && 
                lockManager.holdsLock(1, "table1") && 
                lockManager.holdsLock(2, "table1")) {
                System.out.println("✓ 多个事务成功获取共享锁（SHARED与SHARED兼容）");
                passedTests++;
            } else {
                System.out.println("✗ 共享锁兼容性测试失败");
            }
        } catch (Exception e) {
            System.out.println("✗ 异常: " + e.getMessage());
        }
        totalTests++;
        System.out.println();
        
        // 测试4: 共享锁与排他锁冲突
        System.out.println("【测试4】共享锁与排他锁冲突");
        try {
            LockManager lockManager = new LockManager(1000); // 1秒超时
            lockManager.acquireLock(1, "table1", LockManager.LockType.SHARED);
            
            long startTime = System.currentTimeMillis();
            boolean result = lockManager.acquireLock(2, "table1", LockManager.LockType.EXCLUSIVE);
            long endTime = System.currentTimeMillis();
            
            if (!result && (endTime - startTime) >= 1000) {
                System.out.println("✓ 排他锁被共享锁阻塞，超时返回（SHARED与EXCLUSIVE不兼容）");
                passedTests++;
            } else {
                System.out.println("✗ 锁冲突处理异常");
            }
        } catch (Exception e) {
            System.out.println("✗ 异常: " + e.getMessage());
        }
        totalTests++;
        System.out.println();
        
        // 测试5: 排他锁阻塞其他锁
        System.out.println("【测试5】排他锁阻塞其他锁");
        try {
            LockManager lockManager = new LockManager(1000);
            lockManager.acquireLock(1, "table1", LockManager.LockType.EXCLUSIVE);
            
            long startTime = System.currentTimeMillis();
            boolean result = lockManager.acquireLock(2, "table1", LockManager.LockType.SHARED);
            long endTime = System.currentTimeMillis();
            
            if (!result && (endTime - startTime) >= 1000) {
                System.out.println("✓ 共享锁被排他锁阻塞，超时返回（EXCLUSIVE与SHARED不兼容）");
                passedTests++;
            } else {
                System.out.println("✗ 排他锁阻塞测试失败");
            }
        } catch (Exception e) {
            System.out.println("✗ 异常: " + e.getMessage());
        }
        totalTests++;
        System.out.println();
        
        // 测试6: 释放锁
        System.out.println("【测试6】释放锁");
        try {
            LockManager lockManager = new LockManager();
            lockManager.acquireLock(1, "table1", LockManager.LockType.SHARED);
            lockManager.releaseLock(1, "table1");
            
            if (!lockManager.holdsLock(1, "table1")) {
                System.out.println("✓ 成功释放锁");
                passedTests++;
            } else {
                System.out.println("✗ 释放锁失败");
            }
        } catch (Exception e) {
            System.out.println("✗ 异常: " + e.getMessage());
        }
        totalTests++;
        System.out.println();
        
        // 测试7: 释放后其他事务可获取排他锁
        System.out.println("【测试7】释放后其他事务可获取排他锁");
        try {
            LockManager lockManager = new LockManager();
            lockManager.acquireLock(1, "table1", LockManager.LockType.SHARED);
            lockManager.releaseLock(1, "table1");
            
            boolean result = lockManager.acquireLock(2, "table1", LockManager.LockType.EXCLUSIVE);
            
            if (result) {
                System.out.println("✓ 释放锁后，其他事务成功获取排他锁");
                passedTests++;
            } else {
                System.out.println("✗ 释放后获取锁失败");
            }
        } catch (Exception e) {
            System.out.println("✗ 异常: " + e.getMessage());
        }
        totalTests++;
        System.out.println();
        
        // 测试8: 释放所有锁
        System.out.println("【测试8】释放事务的所有锁");
        try {
            LockManager lockManager = new LockManager();
            lockManager.acquireLock(1, "table1", LockManager.LockType.SHARED);
            lockManager.acquireLock(1, "table2", LockManager.LockType.SHARED);
            lockManager.acquireLock(1, "table3", LockManager.LockType.EXCLUSIVE);
            
            int beforeCount = lockManager.getLockCount(1);
            lockManager.releaseAllLocks(1);
            int afterCount = lockManager.getLockCount(1);
            
            if (beforeCount == 3 && afterCount == 0) {
                System.out.println("✓ 成功释放事务的所有锁（3个）");
                passedTests++;
            } else {
                System.out.println("✗ 释放所有锁失败");
            }
        } catch (Exception e) {
            System.out.println("✗ 异常: " + e.getMessage());
        }
        totalTests++;
        System.out.println();
        
        // 测试9: 锁升级（共享锁 -> 排他锁）
        System.out.println("【测试9】锁升级（共享锁 -> 排他锁）");
        try {
            LockManager lockManager = new LockManager();
            lockManager.acquireLock(1, "table1", LockManager.LockType.SHARED);
            boolean result = lockManager.acquireLock(1, "table1", LockManager.LockType.EXCLUSIVE);
            
            if (result) {
                System.out.println("✓ 成功升级锁：SHARED -> EXCLUSIVE");
                passedTests++;
            } else {
                System.out.println("✗ 锁升级失败");
            }
        } catch (Exception e) {
            System.out.println("✗ 异常: " + e.getMessage());
        }
        totalTests++;
        System.out.println();
        
        // 测试10: 锁升级时有其他共享锁（超时）
        System.out.println("【测试10】锁升级冲突（有其他共享锁持有者）");
        try {
            LockManager lockManager = new LockManager(1000);
            lockManager.acquireLock(1, "table1", LockManager.LockType.SHARED);
            lockManager.acquireLock(2, "table1", LockManager.LockType.SHARED);
            
            long startTime = System.currentTimeMillis();
            boolean result = lockManager.acquireLock(1, "table1", LockManager.LockType.EXCLUSIVE);
            long endTime = System.currentTimeMillis();
            
            if (!result && (endTime - startTime) >= 1000) {
                System.out.println("✓ 锁升级被阻塞，超时返回（有其他共享锁持有者）");
                passedTests++;
            } else {
                System.out.println("✗ 锁升级冲突处理异常");
            }
        } catch (Exception e) {
            System.out.println("✗ 异常: " + e.getMessage());
        }
        totalTests++;
        System.out.println();
        
        // 测试11: 并发测试 - 多线程竞争
        System.out.println("【测试11】并发测试 - 多线程竞争同一资源");
        try {
            LockManager lockManager = new LockManager(2000);
            int threadCount = 10;
            CountDownLatch latch = new CountDownLatch(threadCount);
            AtomicInteger successCount = new AtomicInteger(0);
            
            ExecutorService executor = Executors.newFixedThreadPool(threadCount);
            
            for (int i = 0; i < threadCount; i++) {
                final long txnId = i + 1;
                executor.submit(() -> {
                    try {
                        if (lockManager.acquireLock(txnId, "shared_resource", 
                                                    LockManager.LockType.EXCLUSIVE)) {
                            successCount.incrementAndGet();
                            Thread.sleep(100); // 持有锁一段时间
                            lockManager.releaseLock(txnId, "shared_resource");
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        latch.countDown();
                    }
                });
            }
            
            latch.await(30, TimeUnit.SECONDS);
            executor.shutdown();
            
            if (successCount.get() <= threadCount && successCount.get() > 0) {
                System.out.println("✓ 并发测试通过，成功获取锁: " + successCount.get() + "/" + threadCount);
                passedTests++;
            } else {
                System.out.println("✗ 并发测试异常");
            }
        } catch (Exception e) {
            System.out.println("✗ 异常: " + e.getMessage());
            e.printStackTrace();
        }
        totalTests++;
        System.out.println();
        
        // 测试12: 并发测试 - 读写混合
        System.out.println("【测试12】并发测试 - 多个读者与一个写者");
        try {
            LockManager lockManager = new LockManager(2000);
            CountDownLatch latch = new CountDownLatch(6);
            AtomicInteger readerSuccess = new AtomicInteger(0);
            AtomicInteger writerSuccess = new AtomicInteger(0);
            
            ExecutorService executor = Executors.newFixedThreadPool(6);
            
            // 5个读者
            for (int i = 0; i < 5; i++) {
                final long txnId = i + 1;
                executor.submit(() -> {
                    try {
                        if (lockManager.acquireLock(txnId, "data", LockManager.LockType.SHARED)) {
                            readerSuccess.incrementAndGet();
                            Thread.sleep(100);
                            lockManager.releaseLock(txnId, "data");
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        latch.countDown();
                    }
                });
            }
            
            // 1个写者（稍后启动）
            Thread.sleep(50);
            executor.submit(() -> {
                try {
                    if (lockManager.acquireLock(100, "data", LockManager.LockType.EXCLUSIVE)) {
                        writerSuccess.incrementAndGet();
                        lockManager.releaseLock(100, "data");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    latch.countDown();
                }
            });
            
            latch.await(30, TimeUnit.SECONDS);
            executor.shutdown();
            
            if (readerSuccess.get() == 5) {
                System.out.println("✓ 读写混合测试通过");
                System.out.println("  读者成功: " + readerSuccess.get() + "/5");
                System.out.println("  写者成功: " + writerSuccess.get() + "/1");
                passedTests++;
            } else {
                System.out.println("✗ 读写混合测试失败");
            }
        } catch (Exception e) {
            System.out.println("✗ 异常: " + e.getMessage());
            e.printStackTrace();
        }
        totalTests++;
        System.out.println();
        
        // 测试13: 死锁预防 - 超时机制
        System.out.println("【测试13】死锁预防 - 超时机制测试");
        try {
            LockManager lockManager = new LockManager(500); // 500ms超时
            
            // 事务1持有table1的排他锁
            lockManager.acquireLock(1, "table1", LockManager.LockType.EXCLUSIVE);
            
            // 事务2尝试获取table1的排他锁（应超时）
            long startTime = System.currentTimeMillis();
            boolean result = lockManager.acquireLock(2, "table1", LockManager.LockType.EXCLUSIVE);
            long duration = System.currentTimeMillis() - startTime;
            
            if (!result && duration >= 500 && duration < 1000) {
                System.out.println("✓ 超时机制工作正常");
                System.out.println("  超时时间: " + duration + "ms");
                passedTests++;
            } else {
                System.out.println("✗ 超时机制异常");
            }
        } catch (Exception e) {
            System.out.println("✗ 异常: " + e.getMessage());
        }
        totalTests++;
        System.out.println();
        
        // 测试结果汇总
        System.out.println("========================================");
        System.out.println("           测试结果汇总");
        System.out.println("========================================");
        System.out.println("总测试数: " + totalTests);
        System.out.println("通过数: " + passedTests);
        System.out.println("失败数: " + (totalTests - passedTests));
        System.out.println("通过率: " + String.format("%.1f%%", passedTests * 100.0 / totalTests));
        System.out.println("----------------------------------------");
        
        if (passedTests == totalTests) {
            System.out.println("✓✓✓ 所有测试通过！");
        } else {
            System.out.println("✗✗✗ 部分测试失败");
        }
        System.out.println("========================================\n");
    }
}
